package com.hskn.hss.module.oilDevice.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.hskn.hss.core.controller.BaseController;
import com.hskn.hss.core.utils.poi.ExcelUtil;
import com.hskn.hss.entity.AjaxResult;
import com.hskn.hss.module.attend.vo.AttendanceSummaryVO;
import com.hskn.hss.module.carTrack.entity.CarTrack;
import com.hskn.hss.module.carTrack.mapper.CarTrackMapper;
import com.hskn.hss.module.carTrack.service.CarTrackService;
import com.hskn.hss.module.carviolation.entity.CarViolation;
import com.hskn.hss.module.common.to.OilNumTO;
import com.hskn.hss.module.oilDevice.domain.StateOilDevice;
import com.hskn.hss.module.depart.service.ISysDepartService;
import com.hskn.hss.module.oilDevice.ex.to.OilConsumeExcelTO;
import com.hskn.hss.module.oilDevice.ex.vo.*;
import com.hskn.hss.module.oilDevice.mapper.StateOilDeviceMapper;
import com.hskn.hss.module.oilDevice.service.IStateOilDeviceService;
import com.hskn.hss.module.oilDevice.to.AddOilSummaryTableTO;
import com.hskn.hss.module.oilDevice.to.MileageReportTableTO;
import com.hskn.hss.module.oilDevice.to.OilConsumeTO;
import com.hskn.hss.module.oilDevice.to.OilConsumeTableTO;
import com.hskn.hss.module.oilDevice.vo.MileageTableVO;
import com.hskn.hss.module.oilDevice.vo.OilConsumeVO;
import com.hskn.hss.module.oilDevice.vo.RefuelingSummaryECharsVO;
import com.hskn.hss.module.oilDevice.vo.StayReportTableVO;
import com.hskn.hss.module.tlcar.entity.TlCar;
import com.hskn.hss.module.tlcar.service.ITlCarService;
import com.hskn.hss.task.WorkTask;
import com.hskn.hss.utils.GroupingByUtils;
import com.hskn.hss.utils.LocationUtils;
import com.hskn.hss.utils.StringUtils;
import com.hskn.hss.utils.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 每日油量变化统计Controller
 *
 * @author ruoyi
 * @date 2021-08-05
 */
@Api(tags = {"-state_oil_device"}, description = "油量变化统计")
@RestController
@Slf4j
@RequestMapping("/hss/deviceOil")
public class StateOilDeviceController extends BaseController {

    @Autowired
    WorkTask workTask;
    @Autowired
    CarTrackService carTrackService;
    @Autowired
    ITlCarService carService;
    @Resource
    CarTrackMapper carTrackMapper;
    @Autowired
    LocationUtils locationUtil;
    @Autowired
    private IStateOilDeviceService stateOilDeviceService;
    @Resource
    private StateOilDeviceMapper stateOilDeviceMapper;
    @Autowired
    ISysDepartService departService;

    /**
     * 耗油统计图
     */
    @ApiOperation(value = "耗油统计图", notes = "耗油统计图")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok")
    })
    @PostMapping("/selectStateOilDeviceForBTable")
    public AjaxResult selectStateOilDeviceForBTable(@RequestBody @Validated OilConsumeTO oilConsumeTO) {
        try {
            return AjaxResult.success(stateOilDeviceService.selectStateOilDeviceForBTable(oilConsumeTO));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 耗油列表 也用于漏油 百公里耗油 设备加油列表
     */
    @ApiOperation(value = "耗油列表 也用于漏油 百公里耗油 设备加油列表", notes = "耗油列表 也用于漏油 百公里耗油 设备加油列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = OilConsumeVO.class)
    })
    @PostMapping("/selectStateOilDeviceForTTable")
    public AjaxResult selectStateOilDeviceForTTable(@RequestBody @Validated OilConsumeTableTO oilConsumeTableTO) {
        try {
            if(oilConsumeTableTO.getDepId() != null && oilConsumeTableTO.getDepId() != ""){
                List<String> depIds=departService.getChildIdsByIId(oilConsumeTableTO.getDepId());
                oilConsumeTableTO.setDepIds(depIds);
            }
            Integer pageSize = oilConsumeTableTO.getSize();
            Integer pageNum = oilConsumeTableTO.getPage();
            return AjaxResult.success(Tools.buildTableDataInfo(pageNum,pageSize,stateOilDeviceService.selectStateOilDeviceForTTable(oilConsumeTableTO)));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 各机构加油报表列表
     */
    @ApiOperation(value = "各机构加油报表列表", notes = "各机构加油报表列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = OilConsumeVO.class)
    })
    @PostMapping("/selectStateOilDeviceTableByDepId")
    public AjaxResult selectStateOilDeviceTableByDepId(@RequestBody @Validated AddOilSummaryTableTO addOilSummaryTableTO) {
        try {
            Integer pageSize = addOilSummaryTableTO.getSize();
            Integer pageNum = addOilSummaryTableTO.getPage();
            return AjaxResult.success(Tools.buildTableDataInfo(pageNum,pageSize,stateOilDeviceService.selectStateOilDeviceTableByDepId(addOilSummaryTableTO)));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 各作业类型报表列表
     */
    @ApiOperation(value = "各作业类型报表列表", notes = "各作业类型报表列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = OilConsumeVO.class)
    })
    @PostMapping("/selectStateOilDeviceTableByOperType")
    public AjaxResult selectStateOilDeviceTableByOperType(@RequestBody @Validated AddOilSummaryTableTO addOilSummaryTableTO) {
        try {
            Integer pageSize = addOilSummaryTableTO.getSize();
            Integer pageNum = addOilSummaryTableTO.getPage();
            return AjaxResult.success(Tools.buildTableDataInfo(pageNum,pageSize,stateOilDeviceService.selectStateOilDeviceTableByOperType(addOilSummaryTableTO)));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 各车辆类型报表列表
     */
    @ApiOperation(value = "各车辆类型报表列表", notes = "各车辆类型报表列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = OilConsumeVO.class)
    })
    @PostMapping("/selectStateOilDeviceTableByCarType")
    public AjaxResult selectStateOilDeviceTableByCarType(@RequestBody @Validated AddOilSummaryTableTO addOilSummaryTableTO) {
        try {
            Integer pageSize = addOilSummaryTableTO.getSize();
            Integer pageNum = addOilSummaryTableTO.getPage();
            return AjaxResult.success(Tools.buildTableDataInfo(pageNum,pageSize,stateOilDeviceService.selectStateOilDeviceTableByCarType(addOilSummaryTableTO)));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 漏油统计图
     */
    @ApiOperation(value = "漏油统计图", notes = "漏油统计图")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok")
    })
    @PostMapping("/selectStateOilDeviceOfOutForBTable")
    public AjaxResult selectStateOilDeviceOfOutForBTable(@RequestBody @Validated OilConsumeTO oilConsumeTO) {
        try {
            return AjaxResult.success(stateOilDeviceService.selectStateOilDeviceOfOutForBTable(oilConsumeTO));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 加油统计图
     */
    @ApiOperation(value = "加油统计图", notes = "加油统计图")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok")
    })
    @PostMapping("/selectStateOilDeviceOfAddForBTable")
    public AjaxResult selectStateOilDeviceOfAddForBTable(@RequestBody @Validated OilConsumeTO oilConsumeTO) {
        try {
            return AjaxResult.success(stateOilDeviceService.selectStateOilDeviceOfAddForBTable(oilConsumeTO));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 加油汇总统计图
     */
    @ApiOperation(value = "-加油汇总统计图", notes = "-加油汇总统计图")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = RefuelingSummaryECharsVO.class)
    })
    @PostMapping("/getRefuelingSummaryECharsVO")
    public AjaxResult getRefuelingSummaryECharsVO(@RequestBody @Validated AddOilSummaryTableTO addOilSummaryTableTO) {
        try {
            return AjaxResult.success(stateOilDeviceService.getRefuelingSummaryECharsVO(addOilSummaryTableTO));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 行驶EChars图
     */
    @ApiOperation(value = "行驶EChars图", notes = "行驶EChars图")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok")
    })
    @PostMapping("/selectMileageReportChars")
    public AjaxResult selectMileageReportChars(@RequestBody @Validated MileageReportTableTO mileageReportCharsTO) {
        try {
            return AjaxResult.success(stateOilDeviceService.selectMileageReportChars(mileageReportCharsTO));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 停留EChars图
     */
    @ApiOperation(value = "停留EChars图", notes = "停留EChars图")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok")
    })
    @PostMapping("/stayReportEChars")
    public AjaxResult stayReportEChars(@RequestBody @Validated MileageReportTableTO mileageReportCharsTO) {
        try {
            List<CarViolation> carViolationList = stateOilDeviceService.getCarViolationList(mileageReportCharsTO);
            return AjaxResult.success(stateOilDeviceService.stayReportEChars(carViolationList));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 行驶里程列表
     */
    @ApiOperation(value = "行驶里程列表", notes = "行驶里程列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = MileageTableVO.class)
    })
    @PostMapping("/selectMileageReportTable")
    public AjaxResult selectMileageReportTable(@RequestBody @Validated MileageReportTableTO mileageReportTableTO) {
        try {
            Integer pageSize = mileageReportTableTO.getSize();
            Integer pageNum = mileageReportTableTO.getPage();
            if (pageSize == null || pageNum == null) {
                return AjaxResult.fail("pageNum，pageSize不能为空");
            }
            return AjaxResult.success(stateOilDeviceService.selectMileageReportTable(mileageReportTableTO));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 行驶里程列表
     */
    @ApiOperation(value = "停留列表", notes = "停留列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = StayReportTableVO.class)
    })
    @PostMapping("/stayReportTable")
    public AjaxResult stayReportTable(@RequestBody @Validated MileageReportTableTO mileageReportTableTO) {
        try {
            List<CarViolation> carViolationList = stateOilDeviceService.getCarViolationList(mileageReportTableTO);
            return AjaxResult.success(stateOilDeviceService.stayReportTable(mileageReportTableTO,carViolationList));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }

    /**
     * 行驶里程列表明细
     */
    @ApiOperation(value = "停留列表明细", notes = "停留列表明细")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = StayReportTableVO.class)
    })
    @PostMapping("/stayReportTableDetail")
    public AjaxResult stayReportTableDetail(@RequestBody @Validated MileageReportTableTO mileageReportTableTO) {
        try {
            List<CarViolation> carViolationList = stateOilDeviceService.getCarViolationList(mileageReportTableTO);
            return AjaxResult.success(stateOilDeviceService.stayReportTableDetail(mileageReportTableTO,carViolationList));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.fail();
        }
    }


    /**
     * state_oil_device 修数据
     */
    @PostMapping("/addOil")
    public AjaxResult addOil(@RequestBody @Validated OilNumTO oilNumTO) {
        List<Date> dateList = Tools.getBetweenDateList(oilNumTO.getStartTime(), oilNumTO.getEndTime());
        SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
        for (Date date : dateList) {
            QueryWrapper<StateOilDevice> stateOilDeviceQueryWrapper= new QueryWrapper<>();
            stateOilDeviceQueryWrapper.lambda().between(StateOilDevice::getDeviceDate,Tools.getDateForBegin(date),Tools.getDateForEnd(date));
            List<StateOilDevice> stateOilDeviceList = stateOilDeviceMapper.selectList(stateOilDeviceQueryWrapper);
            if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(stateOilDeviceList)){
                List<String> ids=stateOilDeviceList.stream().map(StateOilDevice::getId).collect(Collectors.toList());
                stateOilDeviceMapper.deleteBatchIds(ids);
            }
            List<CarTrack> carTrackListBeginServenDay = carTrackService.getCarTracks(org.apache.commons.collections4.CollectionUtils
            .isNotEmpty(oilNumTO.getCarIds())?oilNumTO.getCarIds().get(0):null, date);
            workTask.addOil(carTrackListBeginServenDay, date);
            log.info(sp.format(date) + "--RepairRefuelingDataRefuelingDataCompleted");
        }
        return AjaxResult.success();
    }

    /**
     * car_track 修加油数据
     */
    @PostMapping("/calculateAddOilNum2")
    public AjaxResult calculateAddOilNum2(@RequestBody @Validated OilNumTO oilNumTO) {
        List<Date> dateList = Tools.getBetweenDateList(oilNumTO.getStartTime(), oilNumTO.getEndTime());
        OilNumTO oilNumTO2 = new OilNumTO();
        SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
        for (Date date : dateList) {
            oilNumTO2.setStartTime(sp.format(date));
            oilNumTO2.setEndTime(sp.format(date));
            if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(oilNumTO.getCarIds())){
                oilNumTO2.setCarIds(oilNumTO.getCarIds());
            }
            calculateAddOilNum(oilNumTO2);
            log.info(sp.format(date) + "--RepairRefuelingDataRefuelingDataCompleted");
        }
        return AjaxResult.success();
    }

    /**
     * car_track 修加油数据
     */
    @PostMapping("/calculateDistanceBetween")
    public AjaxResult calculateDistanceBetween(@RequestBody @Validated OilNumTO oilNumTO) {
        List<Date> dateList = Tools.getBetweenDateList(oilNumTO.getStartTime(), oilNumTO.getEndTime());
        OilNumTO oilNumTO2 = new OilNumTO();
        SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
        for (Date date : dateList) {
            oilNumTO2.setStartTime(sp.format(date));
            oilNumTO2.setEndTime(sp.format(date));
            buildCalculateDistanceBetween(oilNumTO2);
            log.info(sp.format(date) + "--calculateDistanceBetween");
        }
        return AjaxResult.success();
    }

    public void buildCalculateDistanceBetween(OilNumTO oilNumTO) {
        SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        Double distanceBetween = 0.00;
        Date startDate = null;
        Date endDate = null;
        try {
            startDate = Tools.getDateForBegin(sp.parse(oilNumTO.getStartTime()));
            endDate = Tools.getDateForEnd(sp.parse(oilNumTO.getEndTime()));
            carTrackQueryWrapper.lambda().between(CarTrack::getTimestamp, Tools.getDateForBegin(startDate), Tools.getDateForEnd(endDate));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        if (Objects.nonNull(oilNumTO.getCarIds())) {
            carTrackQueryWrapper.lambda().in(CarTrack::getCarId, oilNumTO.getCarIds());
        }
        carTrackQueryWrapper.lambda().select(CarTrack::getId, CarTrack::getTimestamp, CarTrack::getLat, CarTrack::getLng, CarTrack::getCarId);
        //.eq(CarTrack::getCarId,"41f383dbc10a4ad4865ace468d26f5b7");
        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
        Map<String, List<CarTrack>> carTrackMapAll = GroupingByUtils.getGroupingForMapList(carTrackList, CarTrack::getCarId);
        List<CarTrack> carTrackListOnlyCar = null;
        for (String carId : carTrackMapAll.keySet()) {
            carTrackListOnlyCar = carTrackMapAll.get(carId).stream().sorted(Comparator.comparing(CarTrack::getTimestamp)).collect(Collectors.toList());
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(carTrackListOnlyCar)) {
                continue;
            }
            for (int i = 1; carTrackListOnlyCar.size() > i; i++) {
                carTrackListOnlyCar.get(0).setDistanceBetween(0);
                distanceBetween = locationUtil.getDistance(carTrackListOnlyCar.get(i).getLat(), carTrackListOnlyCar.get(i).getLng()
                        , carTrackListOnlyCar.get(i - 1).getLat(), carTrackListOnlyCar.get(i - 1).getLng());
                carTrackListOnlyCar.get(i).setDistanceBetween(distanceBetween.intValue());
            }
        }
        //System.out.println(carTrackList);
        carTrackService.updateBatchById(carTrackList);
    }

    /**
     * car_track 修加油数据
     */
    @PostMapping("/calculateAddOilNum")
    public void calculateAddOilNum(@RequestBody @Validated OilNumTO oilNumTO) {
        SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
        List<CarTrack> nowCarTrackList = new ArrayList<>();
        List<CarTrack> carTrackListFor = new ArrayList<>();
        List<CarTrack> nowCarTrackList1 = new ArrayList<>();
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();

        Date startDate = null;
        Date endDate = null;
        try {
            startDate = Tools.getDateForBegin(sp.parse(oilNumTO.getStartTime()));
            endDate = Tools.getDateForEnd(sp.parse(oilNumTO.getEndTime()));
            carTrackQueryWrapper.lambda().between(CarTrack::getTimestamp, Tools.getDateForBegin(new Date(Tools.getDateAddNumber(startDate, -24 * 60 * 2))), Tools.getDateForEnd(endDate));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        //carTrackQueryWrapper.lambda().eq(CarTrack::getCarId,"41f383dbc10a4ad4865ace468d26f5b7");
        if (Objects.nonNull(oilNumTO.getCarIds())) {
            carTrackQueryWrapper.lambda().in(CarTrack::getCarId, oilNumTO.getCarIds());
        }
        carTrackQueryWrapper.lambda().select(CarTrack::getOilMass, CarTrack::getTimestamp, CarTrack::getAddOilNum, CarTrack::getCarId, CarTrack::getId, CarTrack::getCreateTime);
        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
        carTrackList = carTrackList.stream().distinct().filter(carTrack -> carTrack.getOilMass().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(carTrackList)) {
            return;
        }
        Date finalStartDate = startDate;
        Date finalEndDate = endDate;
        carTrackListFor = carTrackList.stream().filter(carTrack -> carTrack.getTimestamp().getTime() >= finalStartDate.getTime()
                && carTrack.getTimestamp().getTime() <= finalEndDate.getTime()).collect(Collectors.toList());
        carTrackListFor.forEach(aa -> aa.setAddOilNum(0d));
        Map<String, List<CarTrack>> carTrackMap = GroupingByUtils.getGroupingForMapList(carTrackListFor, CarTrack::getCarId);
        Map<String, List<CarTrack>> carTrackMapAll = GroupingByUtils.getGroupingForMapList(carTrackList, CarTrack::getCarId);


        QueryWrapper<TlCar> carQueryWrapper = new QueryWrapper<TlCar>();
        carQueryWrapper.lambda().in(TlCar::getId, carTrackMap.keySet());
        Map<String, TlCar> carMap = carService.getCarMap(carQueryWrapper);

        for (String carId : carTrackMap.keySet()) {
            nowCarTrackList = carTrackMap.get(carId);
            for (int i = 0; i < nowCarTrackList.size(); i++) {
                if (i != 0 && nowCarTrackList.get(i).getOilMass().equals(nowCarTrackList.get(i - 1).getOilMass()) && nowCarTrackList.get(i).getTimestamp().getTime() == nowCarTrackList.get(i - 1).getTimestamp().getTime()) {
                    continue;
                }
                CarTrack carTrack = nowCarTrackList.get(i);
                nowCarTrackList1 = carTrackMapAll.get(carTrack.getCarId()).stream().sorted(Comparator.comparing(CarTrack::getTimestamp).reversed())
                        .filter(carTrack1 -> carTrack1.getTimestamp().getTime() < carTrack.getTimestamp().getTime()).collect(Collectors.toList());
                if (nowCarTrackList1.size() < 200) {
                    QueryWrapper<CarTrack> carTrackQueryWrapper2 = new QueryWrapper<>();
                    carTrackQueryWrapper2.lambda().lt(CarTrack::getTimestamp, startDate);
                    carTrackQueryWrapper2.lambda().orderByDesc(CarTrack::getTimestamp);
                    carTrackQueryWrapper2.lambda().select(CarTrack::getOilMass, CarTrack::getTimestamp, CarTrack::getAddOilNum, CarTrack::getCarId, CarTrack::getId, CarTrack::getCreateTime);
                    carTrackQueryWrapper2.lambda().eq(CarTrack::getCarId, carTrack.getCarId());
                    carTrackQueryWrapper2.lambda().last("limit 200");
                    List<CarTrack> carTrackList2 = carTrackMapper.selectList(carTrackQueryWrapper2);
                    nowCarTrackList1.addAll(carTrackList2);
                    nowCarTrackList1 = nowCarTrackList1.stream().distinct().sorted(Comparator.comparing(CarTrack::getTimestamp).reversed()).collect(Collectors.toList());
                }
                Double num = calculateAddOilNum(nowCarTrackList1.stream().filter(carTrack11 -> carTrack11.getOilMass().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList()), 5, carTrack.getOilMass());
                nowCarTrackList.get(i).setAddOilNum(num);
            }
        }
        carTrackListFor.forEach(carTrack -> carTrack.setAddOilProp(new BigDecimal(carTrack.getAddOilNum()).divide(new BigDecimal(carMap.containsKey(carTrack.getCarId()) && StringUtils.isNotEmpty((carMap.get(carTrack.getCarId()).getTankvolcheck())) ? Integer.valueOf(carMap.get(carTrack.getCarId()).getTankvolcheck()) : 75), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue()));
        carTrackService.updateBatchById(carTrackListFor);
        for (CarTrack carTrack : carTrackListFor) {
            if (carTrack.getAddOilNum()>0) {
                System.out.println("id:" + carTrack.getId() + "carId:" + carTrack.getCarId() + ",timestamp:" + DateUtil.formatDateTime(carTrack.getTimestamp()) + ",createTime:" + DateUtil.formatDateTime(carTrack.getCreateTime()) + ",oilNum:" + carTrack.getOilMass() + ",addOilNum:" + carTrack.getAddOilNum());
            }
        }
        nowCarTrackList = null;
        carTrackListFor = null;
        nowCarTrackList1 = null;
    }

    private Double calculateAddOilNum(List<CarTrack> carTrackList, Integer flag, BigDecimal nowOilNum) {
        if (nowOilNum.compareTo(BigDecimal.ZERO) <= 0) {
            return 0.0;
        }
        if (CollectionUtils.isEmpty(carTrackList)) {
            return 0.0;
        }
        if (carTrackList.get(0).getAddOilNum() != null && carTrackList.get(0).getAddOilNum() > 0) {
            if (nowOilNum.subtract(carTrackList.get(0).getOilMass()).compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal value = nowOilNum.
                        subtract(carTrackList.get(0).getOilMass()).
                        setScale(2, BigDecimal.ROUND_HALF_UP);
                return value.doubleValue();
            }
        } else {
            BigDecimal sum = nowOilNum.subtract(carTrackList.get(0).getOilMass());
            for (int i = 0; i < carTrackList.size() - 1; i++) {
                if (carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO) <= 0 || nowOilNum.compareTo(BigDecimal.ZERO) <= 0 || carTrackList.get(i + 1).getOilMass().compareTo(BigDecimal.ZERO) <= 0) {
                    continue;
                }
                BigDecimal o = carTrackList.get(i).getOilMass().subtract(carTrackList.get(i + 1).getOilMass());
                if (o.compareTo(BigDecimal.ZERO) >= 0) {
                    sum = sum.add(o);
                } else {
                    break;
                }
                if (sum.compareTo(new BigDecimal(String.valueOf(flag))) >= 0) {
                    break;
                }
            }

            if (sum.compareTo(new BigDecimal(String.valueOf(flag))) >= 0) {
                for (int i = 0; i < carTrackList.size() - 1; i++) {
                    if (carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO) <= 0 || nowOilNum.compareTo(BigDecimal.ZERO) <= 0 || carTrackList.get(i + 1).getOilMass().compareTo(BigDecimal.ZERO) <= 0) {
                        continue;
                    }
                    BigDecimal o = carTrackList.get(i).getOilMass().subtract(carTrackList.get(i + 1).getOilMass());
                    if (o.compareTo(BigDecimal.ZERO) >= 0) {
                        BigDecimal val = carTrackList.get(i).getOilMass().
                                subtract(carTrackList.get(i + 1).getOilMass()).
                                setScale(2, BigDecimal.ROUND_HALF_UP);
                        System.out.println("---------------d---------------" + val + "---------------d-----------------");
                        System.out.println("---------------c---------------" + carTrackList.get(i).getCarId() + "---------------c-----------------");
                        carTrackList.get(i).setAddOilNum(val.doubleValue());
                    } else {
                        break;
                    }
                }
                if (null != carTrackList.get(0).getOilMass() && nowOilNum.subtract(carTrackList.get(0).getOilMass()).compareTo(BigDecimal.ZERO) > 0) {
                    return nowOilNum.
                            subtract(carTrackList.get(0).getOilMass()).
                            setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                } else {
                    return 0.0;
                }
            }
        }
        return 0.0;
    }

    /**
     * 耗油报表，百公里耗油查询，漏油报表，设备加油报表导出
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "耗油报表，百公里耗油查询，漏油报表，设备加油报表导出接口", notes = "耗油报表，百公里耗油查询，漏油报表，设备加油报表导出")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = AttendanceSummaryVO.class)
    })
    @PostMapping("selectStateOilExcelExport")
    public com.hskn.hss.core.domain.AjaxResult selectStateOilExcelExport(HttpServletRequest request, @RequestBody OilConsumeExcelTO oilConsumeExcelTO) {
        try {
            if( (oilConsumeExcelTO.getCarIds() == null || oilConsumeExcelTO.getCarIds().size()>0)
                && (oilConsumeExcelTO.getTimes() == null || oilConsumeExcelTO.getTimes().size()>0)
            ) {
            /**
             * 耗油报表 油量信息类型 1:耗油,2:漏油,3:加油,4:百公里耗油
             */
            if (oilConsumeExcelTO.getOilType() == 1) {
                //耗油报表 是否每天1：是，0：否
                if (oilConsumeExcelTO.getIsEve() == 0) {
                    //耗油报表实例
                    List<OilConsumeExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), OilConsumeExcelVO.class);
                    //工具类实例化
                    ExcelUtil<OilConsumeExcelVO> util = new ExcelUtil<>(OilConsumeExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "耗油报表");
                    //耗油明细 是否每天1：是，0：否
                } else if (oilConsumeExcelTO.getIsEve() == 1) {
                    //耗油明细实例
                    List<OilConsumeExceldtVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), OilConsumeExceldtVO.class);
                    //日期格式转换"yyyy-MM-dd"
                    for (OilConsumeExceldtVO vo : oilDeviceServiceVOList) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        String time = sdf.format(vo.getDeviceDate());
                        vo.setYmd(time);
                    }
                    //工具类实例化
                    ExcelUtil<OilConsumeExceldtVO> util = new ExcelUtil<>(OilConsumeExceldtVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "耗油明细");
                }
                /**
                 * 百公里耗油查询 油量信息类型 1:耗油,2:漏油,3:加油,4:百公里耗油
                 */
            } else if (oilConsumeExcelTO.getOilType() == 4) {
                //百公里耗油报表实例
                List<HKOilConsumeExcelVO> oilDeviceServiceVOList =
                        JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), HKOilConsumeExcelVO.class);
                //工具类实例化
                ExcelUtil<HKOilConsumeExcelVO> util = new ExcelUtil<>(HKOilConsumeExcelVO.class);
                //导出
                return util.exportExcel(oilDeviceServiceVOList, "百公里耗油报表");
                /**
                 * 漏油报表 油量信息类型 1:耗油,2:漏油,3:加油,4:百公里耗油
                 */
            } else if (oilConsumeExcelTO.getOilType() == 2) {
                //漏油报表 是否每天1：是，0：否
                if (oilConsumeExcelTO.getIsEve() == 0) {
                    //漏油报表实例
                    List<OilLeakExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), OilLeakExcelVO.class);
                    //工具类实例化
                    ExcelUtil<OilLeakExcelVO> util = new ExcelUtil<>(OilLeakExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "漏油报表");
                    //漏油明细 是否每天1：是，0：否
                } else if (oilConsumeExcelTO.getIsEve() == 1) {
                    //漏油明细实例
                    List<OilLeakExceldtVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), OilLeakExceldtVO.class);
                    //日期格式转换"yyyy-MM-dd"
                    for (OilLeakExceldtVO vo : oilDeviceServiceVOList) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        String time = sdf.format(vo.getDeviceDate());
                        vo.setYmd(time);
                    }
                    //工具类实例化
                    ExcelUtil<OilLeakExceldtVO> util = new ExcelUtil<>(OilLeakExceldtVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "漏油明细");
                }
                /**
                 * 设备加油报表 油量信息类型 1:耗油,2:漏油,3:加油,4:百公里耗油
                 */
            } else if (oilConsumeExcelTO.getOilType() == 3) {
                //设备加油报表 是否每天1：是，0：否
                if (oilConsumeExcelTO.getIsEve() == 0) {
                    //加油报表实例
                    List<OilRefuelExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), OilRefuelExcelVO.class);
                    //工具类实例化
                    ExcelUtil<OilRefuelExcelVO> util = new ExcelUtil<>(OilRefuelExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "加油报表");
                    //设备加油明细 是否每天1：是，0：否
                } else if (oilConsumeExcelTO.getIsEve() == 1) {
                    //加油明细实例
                    List<OilRefuelExceldtVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceForExcel(oilConsumeExcelTO)), OilRefuelExceldtVO.class);
                    //日期格式转换"yyyy-MM-dd"
                    for (OilRefuelExceldtVO vo : oilDeviceServiceVOList) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        String time = sdf.format(vo.getDeviceDate());
                        vo.setYmd(time);
                    }
                    //工具类实例化
                    ExcelUtil<OilRefuelExceldtVO> util = new ExcelUtil<>(OilRefuelExceldtVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "加油明细");
                }
            }
            return com.hskn.hss.core.domain.AjaxResult.error();
            }else{
                return com.hskn.hss.core.domain.AjaxResult.error("请选择至少一条数据导出");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return com.hskn.hss.core.domain.AjaxResult.error();
        }

    }

    /**
     * 加油汇总导出
     */
    @ApiOperation(value = "加油汇总导出接口", notes = "加油汇总导出")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = OilConsumeVO.class)
    })
    @PostMapping("/AddOilSummaryExcel")
    public com.hskn.hss.core.domain.AjaxResult AddOilSummaryExcel(@RequestBody @Validated AddOilSummaryTableTO addOilSummaryTableTO) {
        try {
            /**
             * 各机构加油汇总报表 1:机构,2:作业,3:车型
             */
            if( addOilSummaryTableTO.getOilType() == 3 && (addOilSummaryTableTO.getCarTypeIds() == null || addOilSummaryTableTO.getCarTypeIds().size()>0)
                    ||addOilSummaryTableTO.getOilType() == 1 && (addOilSummaryTableTO.getDeptidforcarIds() == null || addOilSummaryTableTO.getDeptidforcarIds().size()>0)
                    ||addOilSummaryTableTO.getOilType() == 2 && (addOilSummaryTableTO.getCarcategoryNames() == null|| addOilSummaryTableTO.getCarcategoryNames().size()>0))
                {
                if (addOilSummaryTableTO.getOilType() == 1) {
                    List<OilMechExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceTableByDepId(addOilSummaryTableTO)), OilMechExcelVO.class);
                    //工具类实例化
                    ExcelUtil<OilMechExcelVO> util = new ExcelUtil<>(OilMechExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "各机构加油报表");
                    /**
                     * 各作业分类加油汇总报表 1:机构,2:作业,3:车型
                     */
                } else if (addOilSummaryTableTO.getOilType() == 2) {
                    List<OilJobExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceTableByOperType(addOilSummaryTableTO)), OilJobExcelVO.class);
                    //工具类实例化
                    ExcelUtil<OilJobExcelVO> util = new ExcelUtil<>(OilJobExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "各作业分类加油报表");
                    /**
                     * 各车型加油汇总报表 1:机构,2:作业,3:车型
                     */
                } else if (addOilSummaryTableTO.getOilType() == 3) {
                    List<OilCarExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectStateOilDeviceTableByCarType(addOilSummaryTableTO)), OilCarExcelVO.class);
                    //工具类实例化
                    ExcelUtil<OilCarExcelVO> util = new ExcelUtil<>(OilCarExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "各车型加油报表");
                }
                return com.hskn.hss.core.domain.AjaxResult.error();
            }else{
                return com.hskn.hss.core.domain.AjaxResult.error("请选择至少一条数据导出");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return com.hskn.hss.core.domain.AjaxResult.error();
        }
    }

    /**
     * 行驶里程列表导出
     *
     * @return
     */
    @ApiOperation(value = "行驶里程列表导出", notes = "行驶里程列表导出")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = MileageTableVO.class)
    })
    @PostMapping("/selectMileageReportExcel")
    public com.hskn.hss.core.domain.AjaxResult selectMileageReportExcel(@RequestBody @Validated MileageReportTableTO mileageReportTableTO) {
        try {
            if((mileageReportTableTO.getCarIds() == null || mileageReportTableTO.getCarIds().size()>0)
                &&(mileageReportTableTO.getTimes() == null || mileageReportTableTO.getTimes().size()>0)
            ){
            /**
             * 行驶报表 是否每天1：是，0：否
             */
            if (mileageReportTableTO.getIsEve() == 0) {
                List<MileageExcelVO> oilDeviceServiceVOList =
                        JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectMileageReportTableExcel(mileageReportTableTO)), MileageExcelVO.class);
                //工具类实例化
                ExcelUtil<MileageExcelVO> util = new ExcelUtil<>(MileageExcelVO.class);
                //导出
                return util.exportExcel(oilDeviceServiceVOList, "行驶里程列表");
                /**
                 * 每日明细 是否每天1：是，0：否
                 */
            } else if (mileageReportTableTO.getIsEve() == 1) {
                List<MileageExceldtVO> oilDeviceServiceVOList =
                        JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.selectMileageReportTableExcel(mileageReportTableTO)), MileageExceldtVO.class);
                //日期格式转换"yyyy-MM-dd"
                for (MileageExceldtVO vo : oilDeviceServiceVOList) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    if (StringUtils.isNotEmpty(vo.getStartDate()) && StringUtils.isNotEmpty(vo.getStartDate())) {
                        vo.setStartYmd(sdf.format(vo.getStartDate()));
                        vo.setEndYmd(sdf.format(vo.getEndDate()));
                    }
                }
                //工具类实例化
                ExcelUtil<MileageExceldtVO> util = new ExcelUtil<>(MileageExceldtVO.class);
                //导出
                return util.exportExcel(oilDeviceServiceVOList, "行驶里程明细列表");
            }
            return com.hskn.hss.core.domain.AjaxResult.error();
            } else {
                return com.hskn.hss.core.domain.AjaxResult.error("请选择至少一条数据导出");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return com.hskn.hss.core.domain.AjaxResult.error();
        }

    }

    /**
     * 行驶里程列表(停留列表）导出
     *
     * @return
     */
    @ApiOperation(value = "停留列表", notes = "停留列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "ok", response = StayReportTableVO.class)
    })
    @PostMapping("/stayReportExcel")
    public com.hskn.hss.core.domain.AjaxResult stayReportExcel(@RequestBody @Validated MileageReportTableTO mileageReportTableTO) {
        try {
            List<CarViolation> carViolationList = stateOilDeviceService.getCarViolationList(mileageReportTableTO);
            if((mileageReportTableTO.getCarIds() == null || mileageReportTableTO.getCarIds().size()>0)
                    && (mileageReportTableTO.getTimes() == null || mileageReportTableTO.getTimes().size()>0)
            ) {
                /**
                 * 停留列表 是否每天1：是，0：否
                 */
                if (mileageReportTableTO.getIsEve() == 0) {
                    List<StayReportExcelVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.stayReportTableExcel(carViolationList)), StayReportExcelVO.class);
                    //工具类实例化
                    ExcelUtil<StayReportExcelVO> util = new ExcelUtil<>(StayReportExcelVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "停留列表");
                    /**
                     * 停留明细 是否每天1：是，0：否
                     */
                } else if (mileageReportTableTO.getIsEve() == 1) {
                    List<StayReportExceldtVO> oilDeviceServiceVOList =
                            JSONArray.parseArray(JSONObject.toJSONString(stateOilDeviceService.stayReportTableDetailExcel(carViolationList)), StayReportExceldtVO.class);
                    if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(mileageReportTableTO.getTimes())) {
                        Predicate<StayReportExceldtVO> inTime = x -> (mileageReportTableTO.getTimes().contains(x.getStayStartTime().concat(",").concat(x.getStayEndTime())));
                        oilDeviceServiceVOList = oilDeviceServiceVOList.stream().filter(inTime).collect(Collectors.toList());
                    }

                    //工具类实例化
                    ExcelUtil<StayReportExceldtVO> util = new ExcelUtil<>(StayReportExceldtVO.class);
                    //导出
                    return util.exportExcel(oilDeviceServiceVOList, "停留明细");
                }
                return com.hskn.hss.core.domain.AjaxResult.error();
            }else {
                return com.hskn.hss.core.domain.AjaxResult.error("请选择至少一条数据导出");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return com.hskn.hss.core.domain.AjaxResult.error();
        }
    }
}
